﻿// ———————————————————————–
// <copyright file="IPAWSForwarderService.cs" company="The MITRE Corporation">
//    Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// IPAWSForwarderService.cs - Receives inbound EDXL DE and CAP messages, signs them with
// specified IPAWS certificate, and posts them to IPAWS
// Project: IPAWSForwarder
//
// Language:    C#, .NET 4.0
// Platform:    Windows 7, VS 2010
// Author:      Brian Wilkins The MITRE Corporation
/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using IPAWSProxyLib;
using EDXLSharp.CAPLib;
using EDXLSharp.EDXLDELib;
using System.Xml.Linq;
using System.Collections.Specialized;
using System.ServiceModel.Web;
using System.Net;

namespace IPAWSForwardService
{
  /// <summary>
  /// This class serves as the main connection point to the IPAWS EDXL SOAP Services.
  /// </summary>
  [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
  class IPAWSForwarderService:IIPAWSForwarderService
  {
    #region Private Member Variables
    /// <summary>
    /// IPAWS Proxy for CAP 1.2
    /// </summary>
    IPAWS_CAP12Proxy cap12Proxy;

    /// <summary>
    /// IPAWS Proxy for CAP 1.1
    /// </summary>
    CAPProxy cap11Proxy;
    
    /// <summary>
    /// IPAWS Proxy for DE 1.0
    /// </summary>
    EDXLProxy edxlProxy;
    #endregion Private Member Variables

    #region Constructors
    /// <summary>
    /// Initializes the IPAWSForwarderService class and starts the IPAWS proxies.
    /// </summary>
    /// <param name="CogId">Authorized COG Id</param>
    /// <param name="CogUser">Authorized COD User</param>
    public IPAWSForwarderService(int CogId, string CogUser)
    {
      cap11Proxy = new CAPProxy(CogId, CogUser);
      cap12Proxy = new IPAWS_CAP12Proxy(CogId, CogUser);
      edxlProxy = new EDXLProxy(CogId, CogUser);
    }
    #endregion Constructors

    #region Public Member Functions
    /// <summary>
    /// PostCAP12Data receives an XML element representing a CAP 1.2 message.  Forwards the
    /// message on to IPAWS without validating against a particular IPAWS channel profile.
    /// </summary>
    /// <param name="Data">CAP 1.2 XML element</param>
    /// <returns>Success or failure</returns>
    public XElement PostCAP12Data(XElement Data)
    {
      return PostCAP12DataWithProfile(Data, "");
    }

    /// <summary>
    /// PostCAP11Data receives an XML element representing a CAP 1.1 message and forwards to IPAWS.
    /// </summary>
    /// <param name="Data">CAP 1.1 XML element</param>
    /// <returns>Success or failure</returns>
    public XElement PostCAP11Data(XElement Data)
    {
      if (Data != null)
      {
        if (cap11Proxy != null)
        {
          try
          {
            string s = Data.ToString(SaveOptions.None);

            CAP edxlCap = new CAP();
            edxlCap.CAPv11_IPAWSProfilev10 = s;

            Console.WriteLine("");
            Console.WriteLine("Posting CAP 1.1 Message - " + edxlCap.MessageID + " from " + edxlCap.SenderID);
            cap11Proxy.PostMessage(edxlCap);
            Console.WriteLine("Post Succeeded");

            return new XElement("Success");
          }
          catch (Exception Ex)
          {
            Console.WriteLine("Post Failed with error:" + Ex.ToString());
            throw Ex;
          }
        }
      }
      throw new System.ArgumentNullException("Data was null");
    }

    /// <summary>
    /// PostCAP12DataWithProfile receives an XML element representing a CAP 1.2 message.  Forwards the
    /// message on to IPAWS after validating against a particular IPAWS channel profile.
    /// </summary>
    /// <param name="Data">CAP 1.2 XML element</param>
    /// <param name="ProfileName">Profile Name to validate</param>
    /// <returns>Success or failure</returns>
    public XElement PostCAP12DataWithProfile(XElement Data, string ProfileName)
    {
      if (Data != null)
      {
        if (cap12Proxy != null)
        {
          try
          {
            string s = Data.ToString(SaveOptions.None);

            CAP edxlCap = new CAP(s);

            edxlCap.ValidateToIPAWSProfilev10ForCAPv12();

            //validate against a particular channel profile for IPAWS
            if (!string.IsNullOrWhiteSpace(ProfileName))
            {
              if (ProfileName.Equals("EAS"))
              {
                edxlCap.ValidateToIPAWS_EASProfilev10ForCAPv12();
              }
              else if (ProfileName.Equals("CMAS"))
              {
                edxlCap.ValidateToIPAWS_CMASProfilev10ForCAPv12();
              }
              else if (ProfileName.Equals("EAS-CMAS") || ProfileName.Equals("CMAS-EAS") ||
                ProfileName.Equals("EASCMAS") || ProfileName.Equals("CMASEAS"))
              {
                edxlCap.ValidateToIPAWS_EASProfilev10ForCAPv12();
                edxlCap.ValidateToIPAWS_CMASProfilev10ForCAPv12();
              }
            }

            Console.WriteLine("");
            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - Posting CAP 1.2 " + (string.IsNullOrWhiteSpace(ProfileName) ? "" : ProfileName) + " Message - " + edxlCap.MessageID + " from " + edxlCap.SenderID);
            List<NameValueCollection> returnParams = null;

            bool postResult = cap12Proxy.PostMessage(edxlCap, ref returnParams);

            if (!postResult)
            {
              Console.WriteLine("Post Failed");
              WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
              WebOperationContext.Current.OutgoingResponse.StatusDescription = "Post Failed.  No parameters returned from IPAWS.";
              return new XElement("Failure");
            }

            Console.WriteLine("Post Succeeded");

            XElement root = new XElement("Success");

            //wrap up IPAWS return information into simple XElement for return
            if (returnParams != null)
            {
              int i = 1;
              foreach (NameValueCollection nvc in returnParams)
              {
                XElement param = new XElement("ParamList" + i.ToString());

                int j = 1;
                foreach (string key in nvc.AllKeys)
                {
                  if (key != null)
                  {
                    XElement subParam = new XElement("param" + j.ToString());
                    subParam.SetValue(key);
                    param.Add(subParam);

                    XElement subParamValue = new XElement("value" + j.ToString());

                    string val = nvc.Get(key);
                    if (val != null)
                    {
                      subParamValue.SetValue(val);
                    }
                    param.Add(subParamValue);
                    j++;
                  }
                  Console.WriteLine(key + " - " + nvc.Get(key));
                }
                i++;
                root.Add(param);
              }
            }
            return root;
          }
          catch(Exception Ex)
          {
            Console.WriteLine("Post Failed with error:" + Ex.ToString());
            throw Ex;
          }
        }
      }
      throw new System.ArgumentNullException("Data was null");
    }

    /// <summary>
    /// PostDEData receives an XML element representing a DE 1.0 message and forwards it to IPAWS.
    /// </summary>
    /// <param name="Data">DE 1.0 Element</param>
    /// <returns>Success or failure</returns>
    public XElement PostDEData(XElement Data)
    {
      if (Data != null)
      {
        if (edxlProxy != null)
        {
          try
          {
            string s = Data.ToString(SaveOptions.None);

            EDXLDE deObj = new EDXLDE(s);

            Console.WriteLine("");
            Console.WriteLine("Posting DE Message - " + deObj.DistributionID + " from " + deObj.SenderID);
            edxlProxy.PostMessage(deObj);
            Console.WriteLine("Post Succeeded");

            return new XElement("Success");
          }
          catch (Exception Ex)
          {
            Console.WriteLine("Post Failed with error:" + Ex.ToString());
            throw Ex;
          }
        }
      }
      throw new System.ArgumentNullException("Data was null");
    }
    #endregion Public Member Functions
  }
}
